/*
 * Maze.fx
 *
 * Created on 18/03/2010, 11:58:07 AM
 */

package util;

import javafx.scene.CustomNode;
import java.lang.UnsupportedOperationException;
import javafx.scene.Node;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.Group;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.KeyCode;
import javafx.scene.shape.Rectangle;
import javafx.util.Math;
import javafx.scene.shape.ArcType;
import javafx.scene.text.Text;
import javafx.scene.text.Font;



/**
 * @author Alex
 */

public class Maze extends CustomNode{

public var paused = false;

public var pacMan : PacMan = PacMan{ maze:this x:14 y:26};

   public var ghostBlinky = Ghost {
      defaultImage1: Image {
         url: "{__DIR__}images/blinky-aba.png"
       }

      defaultImage2: Image {
         url: "{__DIR__}images/blinky-aba2.png"
       }

       maze: this
       pacMan: pacMan
       personality: 1
       changeFactor: 0.95
       x: 12
       y: 17
       xDirection: 0
       yDirection: -1
       trapTime: 5
      };

   public var ghostPinky = Ghost {
      defaultImage1: Image {
         url: "{__DIR__}images/pinky-aba.png"
       }

      defaultImage2: Image {
         url: "{__DIR__}images/pinky-aba2.png"
       }

       maze: this
       pacMan: pacMan
       personality: 2
       changeFactor: 0.80
       x: 13
       y: 16
       xDirection: 0
       yDirection: -1
       trapTime: 15
      };

   public var ghostInky = Ghost {
      defaultImage1: Image {
         url: "{__DIR__}images/inky-aba1.png"
       }

      defaultImage2: Image {
         url: "{__DIR__}images/inky-aba2.png"
       }

       maze: this
       pacMan: pacMan
       personality: 3
       changeFactor: 0.75
       x: 14
       y: 17
       xDirection: 0
       yDirection: -1
       trapTime: 25
      };

   public var ghostClyde = Ghost {
      defaultImage1: Image {
         url: "{__DIR__}images/clyde-aba.png"
       }

      defaultImage2: Image {
         url: "{__DIR__}images/clyde-aba2.png"
       }

       maze: this
       pacMan: pacMan
       personality: 4
       changeFactor: 0.60
       x: 16
       y: 16
       xDirection: 0
       yDirection: -1
       trapTime: 35
      };

   public var ghosts = [ghostBlinky, ghostPinky, ghostInky, ghostClyde];

   public var dyingPacMan =
     DyingPacMan {
        maze: this
        centerX: 0
        centerY: 0
        radiusX: 13
        radiusY: 13
        startAngle: 90
        length: 360
        type: ArcType.ROUND
        fill: Color.YELLOW
        visible: false
     } ;

   // counter for ghosts eaten
   var ghostEatenCount : Integer;

   // text to be displayed for score of eating a ghost
   var scoreText = [
     ScoreText {
        content: "200"
        visible: false;
      },
     ScoreText {
          content: "400"
          visible: false;
      },
     ScoreText {
          content: "800"
          visible: false;
      },
     ScoreText {
          content: "1600"
          visible: false;
      },
   ];


     var group: Group = Group{
            content: [
                ImageView{
                    x:0;
                    y:0;
                    image: Image {
                        //url: "file:///C:\\Users\\Alex\\Documents\\NetBeansProjects\\proyectoamms2~subversion\\J-PAC-MAN-FX\\src\\images/fondo.png";
                          url: "{__DIR__}images/fondo.png"
                    }
                }
                Text {
                    font: Font {
                            size: 20
                          }
                    x: Map.calcGridX(4)
                    y: Map.calcGridX(1)
                    content: bind "{pacMan.scores} "
                    fill: Color.WHITE

                }
                scoreText,
                dyingPacMan

            ]
        }

  public function makeGhostsHollow() {

    ghostEatenCount = 0;

    for ( g in ghosts )
      g.changeToHollowGhost();
  }

    public function pacManEatsGhost(g: Ghost) {
       ghostEatenCount++;

       var s = 1;
       for ( i in [1..ghostEatenCount] ) s = s + s;

       pacMan.scores += s*100;

       var st = scoreText[ghostEatenCount-1];
       st.x = g.imageX - 10;
       st.y = g.imageY;

       g.stop();
       g.resetStatus();
       g.trapCounter = -10;

       st.showText();
     }
     

   public function pacManMeetsGhosts() {

      for ( g in ghosts )
        if ( hasMet(g) )
          if ( g.isHollow ) {
             pacManEatsGhost(g);
           }
          else {
             for ( ghost in ghosts )
               ghost.stop();

             pacMan.stop();

             dyingPacMan.startAnimation(pacMan.imageX, pacMan.imageY);
             break;
           }
    }

    public function pause() {
        if (this.paused) {
            this.paused = false;
            for (g in ghosts) g.start();
            pacMan.start();
            this.requestFocus();
        }
        else {
            this.paused = true;
            for (g in ghosts) g.stop();
            pacMan.stop();

        }
    }
    


    override protected function create () : Node {
        group
    }

    // determine if pacman meets a ghost
    public function hasMet(g:Ghost): Boolean {

       def distanceThreshold = 22;

       var x1 = g.imageX;
       var x2 = pacMan.imageX;

       var diffX = Math.abs(x1-x2);

       if ( diffX >= distanceThreshold ) return false;

       var y1 = g.imageY;
       var y2 = pacMan.imageY;
       var diffY = Math.abs(y1-y2);

       if ( diffY >= distanceThreshold ) return false;

       // calculate the distance to see if pacman touches the ghost
       if ( diffY*diffY + diffX*diffX <= distanceThreshold*distanceThreshold )
         return true;

       return false;
     }


     public function createDot(  x1: Number,  y1:Number, type:Integer ): Dot {
     var d = Dot {
        x: Map.calcGridX(x1)
        y: Map.calcGridY(y1)
        dotType: type
        visible: true
        }

     if ( d.dotType == Map.MAGIC_DOT )
       d.playTimeline();

 // set the dot type in data model
        Map.setCellData( x1, y1, d.dotType ) ;
        Map.setDot(x1, y1, d);

     return d;
   }

     public function createDot2(  x1: Number,  y1:Number): Dot {
     var d = Dot {
        x: Map.calcGridX(x1)
        y: Map.calcGridY(y1)
        dotType: 3
        visible: true
        }

 // set the dot type in data model

        Map.setDot(x1, y1, d);

     return d;
   }

  // put dots into the maze as a horizontal line
  public function putDotHorizontally(x1: Integer, x2: Integer, y: Number ) {

     var dots =
     for ( x in [ x1..x2] )
       if ( Map.getCellData(x,y) == Map.EMPTY ) {
          var dotType: Integer;

          if ( (x == 26 or x == 1) and (y == 6 or y == 26) )
            dotType = Map.MAGIC_DOT
          else
            dotType = Map.NORMAL_DOT;

          createDot( x, y, dotType )
        }
       else   [] ;

     insert dots into group.content;
   }

  public function putBlocksHorizontally(x1: Integer, x2: Integer, y: Number ) {

     var dots =
     for ( x in [ x1..x2] )
       if ( Map.getCellData(x,y) == Map.EMPTY ) {

          Map.setCellData( x, y, Map.BLOCK ) ;
          createDot2( x, y) ;

        }
       else   [] ;

     //insert dots into group.content;
   }

  public function putBlocksVertically(x: Integer, y1: Integer, y2: Number ) {

     var dots =
     for ( y in [ y1..y2] )
       if ( Map.getCellData(x,y) == Map.EMPTY ) {
          Map.setCellData(x, y, Map.BLOCK)  ;
          createDot2( x, y)
        }
       else  [];

     //insert dots into group.content;
   }

  // put dots into the maze as a vertical line
  public function putDotVertically(x: Integer, y1: Integer, y2: Number ) {

     var dots =
     for ( y in [ y1..y2] )
       if ( Map.getCellData(x,y) == Map.EMPTY ) {
          var dotType: Integer;

          if ( (x == 26 or x == 1) and (y == 6 or y == 26) )
            dotType = Map.MAGIC_DOT
          else
            dotType = Map.NORMAL_DOT;

          createDot( x, y, dotType )
        }
       else  [];

     insert dots into group.content;
   }


  public override var onKeyPressed = function ( e: KeyEvent ) : Void {

     if ( e.code == KeyCode.VK_DOWN )
       pacMan.setKeyboardBuffer( pacMan.MOVE_DOWN )
     else if ( e.code == KeyCode.VK_UP )
       pacMan.setKeyboardBuffer( pacMan.MOVE_UP )
     else if ( e.code == KeyCode.VK_RIGHT )
       pacMan.setKeyboardBuffer( pacMan.MOVE_RIGHT )
     else if ( e.code == KeyCode.VK_LEFT )
       pacMan.setKeyboardBuffer( pacMan.MOVE_LEFT )
     else if (e.code == KeyCode.VK_SPACE)
       pause()


   }

   init {
       focusTraversable = true;
   }


    postinit{
        Map.restartMap();
        putDotHorizontally(1,12,4);
        putDotHorizontally(15,26,4);

        putDotHorizontally(1,26,8);

        putDotHorizontally(1,6,11);
        putDotHorizontally(9,12,11);
        putDotHorizontally(15,18,11);
        putDotHorizontally(21,26,11);

        putDotHorizontally(1,12,23);
        putDotHorizontally(15,26,23);

        putDotHorizontally(1,6,29);
        putDotHorizontally(9,12,29);
        putDotHorizontally(15,18,29);
        putDotHorizontally(21,26,29);

        putDotHorizontally(1,3,26);
        putDotHorizontally(6,12,26);
        putDotHorizontally(15,21,26);
        putDotHorizontally(24,26,26);

        putDotHorizontally(1,26,32);

        putDotVertically(1,4,11);
        putDotVertically(1,23,26);
        putDotVertically(1,29,32);
        putDotVertically(3,27,28);

        putDotVertically(6,4,29);

        putDotVertically(9,8,11);
        putDotVertically(9,26,29);

        putDotVertically(12,4,8);
        putDotVertically(12,23,26);
        putDotVertically(12,29,32);

        putDotVertically(15,4,8);
        putDotVertically(15,23,26);
        putDotVertically(15,29,32);

        putDotVertically(18,8,11);
        putDotVertically(18,26,29);

        putDotVertically(21,4,29);
        putDotVertically(24,27,28);
        putDotVertically(26,4,11);
        putDotVertically(26,23,26);
        putDotVertically(26,29,32);

        putBlocksHorizontally(0,27,3);
        putBlocksHorizontally(2,5,5);
        putBlocksHorizontally(7,11,5);
        putBlocksHorizontally(16,20,5);
        putBlocksHorizontally(22,25,5);
        putBlocksHorizontally(2,5,6);
        putBlocksHorizontally(7,11,6);
        putBlocksHorizontally(16,20,6);
        putBlocksHorizontally(22,25,6);
        putBlocksHorizontally(2,5,7);
        putBlocksHorizontally(7,11,7);
        putBlocksHorizontally(16,20,7);
        putBlocksHorizontally(22,25,7);
        putBlocksHorizontally(2,5,9);
        putBlocksHorizontally(9,17,9);
        putBlocksHorizontally(22,25,9);
        putBlocksHorizontally(2,5,10);
        putBlocksHorizontally(9,17,10);
        putBlocksHorizontally(22,25,10);
        putBlocksHorizontally(0,5,12);
        putBlocksHorizontally(7,11,12);
        putBlocksHorizontally(16,20,12);
        putBlocksHorizontally(22,27,12);
        putBlocksHorizontally(0,5,13);
        putBlocksHorizontally(7,11,13);
        putBlocksHorizontally(16,20,13);
        putBlocksHorizontally(22,27,13);
        putBlocksHorizontally(0,5,15);
        putBlocksHorizontally(10,17,15);
        putBlocksHorizontally(22,27,15);
        putBlocksHorizontally(0,5,19);
        putBlocksHorizontally(10,17,19);
        putBlocksHorizontally(22,27,19);
        putBlocksHorizontally(0,5,21);
        putBlocksHorizontally(10,17,21);
        putBlocksHorizontally(22,27,21);
        putBlocksHorizontally(0,5,22);
        putBlocksHorizontally(10,17,22);
        putBlocksHorizontally(22,27,22);
        putBlocksHorizontally(0,5,16);
        putBlocksHorizontally(22,27,16);
        putBlocksHorizontally(0,5,18);
        putBlocksHorizontally(22,27,18);
        putBlocksHorizontally(2,5,24);
        putBlocksHorizontally(7,11,24);
        putBlocksHorizontally(16,20,24);
        putBlocksHorizontally(22,25,24);
        putBlocksHorizontally(2,5,25);
        putBlocksHorizontally(7,11,25);
        putBlocksHorizontally(16,20,25);
        putBlocksHorizontally(22,25,25);
        putBlocksHorizontally(0,2,27);
        putBlocksHorizontally(10,17,27);
        putBlocksHorizontally(25,27,27);
        putBlocksHorizontally(0,2,28);
        putBlocksHorizontally(10,17,28);
        putBlocksHorizontally(25,27,28);
        putBlocksHorizontally(2,11,30);
        putBlocksHorizontally(16,25,30);
        putBlocksHorizontally(2,11,31);
        putBlocksHorizontally(16,25,31);
        putBlocksHorizontally(0,27,33);

        putBlocksVertically(0,3,12);
        putBlocksVertically(0,22,33);
        putBlocksVertically(4,24,28);
        putBlocksVertically(5,12,16);
        putBlocksVertically(5,18,22);
        putBlocksVertically(5,24,28);

        putBlocksVertically(7,9,16);
        putBlocksVertically(8,9,16);

        putBlocksVertically(7,18,22);
        putBlocksVertically(8,18,22);

        putBlocksVertically(7,27,31);
        putBlocksVertically(8,27,31);

        putBlocksVertically(10,16,19);

        putBlocksVertically(13,3,7);
        putBlocksVertically(14,3,7);

        putBlocksVertically(13,9,13);
        putBlocksVertically(14,9,13);

        putBlocksVertically(13,21,25);
        putBlocksVertically(14,21,25);

        putBlocksVertically(13,27,31);
        putBlocksVertically(14,27,31);

        putBlocksVertically(17,16,19);

        putBlocksVertically(19,9,16);
        putBlocksVertically(20,9,16);

        putBlocksVertically(19,18,22);
        putBlocksVertically(20,18,22);

        putBlocksVertically(19,27,31);
        putBlocksVertically(20,27,31);

        putBlocksVertically(22,12,16);
        putBlocksVertically(22,18,22);
        putBlocksVertically(22,24,28);

        putBlocksVertically(23,24,28);

        putBlocksVertically(27,3,12);
        putBlocksVertically(27,22,33);


        insert pacMan into group.content;

        insert ghosts into group.content;
        
        insert Rectangle {
           x: Map.calcGridX(0) - 7
           y: Map.calcGridY(17) - 15
           width: 29
           height: 29
           strokeWidth: 1
           stroke: Color.BLACK
           fill: Color.BLACK
           visible: true
         } into group.content;

        insert Rectangle {
           x: Map.calcGridX(26) - 6
           y: Map.calcGridY(17) - 15
           width: 29
           height: 29
           strokeWidth: 1
           stroke: Color.BLACK
           fill: Color.BLACK
           visible: true
         } into group.content;

         requestFocus();
        
    }



}
